/* setting.c
 *
 * Copyright (C) 2004-2004 Wang Xiaoguang (Chice) <chice_wxg@hotmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 *
 * Authors: Wang Xiaoguang (Chice) <chice_wxg@hotmail.com>
 */

#include "setting.h"


/*
TODO! & FIXME!

LOCK the file while operating the configuration!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

NOTE: the configuration file always uses \r\n instead of \n
 
*/

static LOCK *settinglock = NULL;

CHAR *setting_find_key(CHAR *buf, CHAR *key, CHAR **valueptr)
{
	CHAR *p, *p1;
	INT keylen;

	p = buf;
	keylen = strlen(key);
	if(valueptr) *valueptr = NULL;

	while(*p)
	{
		if(strnicmp(p, key, keylen) == 0)
		{
		    if(p != buf)
		        if(*(p-1) != '\n')
		            goto continue_while;
		            
			for(p1 = p + keylen; (*p1 != 0) && (*p1 != '='); p1++)
				if(*p1 != ' ' && *p1 != '\t')
					goto continue_while;

			if(*p1 == 0) break;

			if(valueptr) *valueptr = p1 + 1;
			return p;
		}

continue_while:
		p++;
	}
	return NULL;
}

INT setting_get_key_value(CHAR *valueptr, STRING *str)
{
	CHAR *p, *p1;
	INT valuelen;

	p = valueptr;

	if(!p || !str) return 0;

	p1 = strchr(p, '\n');

	if(!p1)
		valuelen = strlen(p);
	else
		valuelen = p1 - p;

	//str = string_assign(str, p);
	//string_truncate(str, valuelen);
	string_truncate(str, 0);
	string_nappend(str, p, valuelen);
	return valuelen;
}


// NOTE:
// filename = NULL to read/write global config ( ~/.MyTunet )
CHAR *setting_load_file(CHAR *filename)
{
	CHAR *tmpbuf;
	CHAR globalconfigfile[1024];
	CHAR *p;
	FILE *fp;
	INT filesize;
	CHAR *comment = "# WARNING: This file is created by MyTunet. DO NOT edit this file!\r\n";

	if(!filename)
	{
		memset(globalconfigfile, 0, sizeof(globalconfigfile));
		strncpy(globalconfigfile, os_get_home_dir(), sizeof(globalconfigfile));

		strncat(globalconfigfile, "/.MyTunet/MyTunet", sizeof(globalconfigfile));

		filename = globalconfigfile;
	}

	fp = fopen(filename, "rb+");
	if(!fp)
	{
		fp = fopen(filename, "wb+");
		if(!fp)
		{
			os_mkdir(globalconfigfile, TRUE);
			fp = fopen(filename, "wb+");
		}
		
		if(fp) fclose(fp);

		tmpbuf = os_new(CHAR, strlen(comment) + 1);
		strcpy(tmpbuf, comment);
		return tmpbuf;

	}

	fseek(fp, 0, SEEK_END);
	filesize = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	tmpbuf = os_new(CHAR, filesize + 1);
	fread(tmpbuf, filesize, 1, fp);
	fclose(fp);

	tmpbuf[filesize] = 0;
	while( (p=strchr(tmpbuf, '\r')) != NULL) *p ='\n';

	return tmpbuf;
}

// NOTE:
// filename = NULL to read/write global config ( ~/.MyTunet )
VOID setting_save_file(CHAR *filename, CHAR *buf)
{
	CHAR *p;
	FILE *fp;
	CHAR globalconfigfile[1024];

	if(!filename)
	{
		memset(globalconfigfile, 0, sizeof(globalconfigfile));
		strncpy(globalconfigfile, os_get_home_dir(), sizeof(globalconfigfile));
		strncat(globalconfigfile, "/.MyTunet/MyTunet", sizeof(globalconfigfile));

		filename = globalconfigfile;
	}

	
    p = buf;

	while( (p=strstr(buf,"\n\n")) != NULL)
	{
		if(*(p-1) != '\r') 
			*p = '\r';
		else
			*(p+1) = '\r';
	}

	p = buf + strlen(buf) - 1;
	if(p)
	{
		while((*p == '\r' || *p =='\n') && (p != buf)) p--;
		p++;
		if(*p) p++;
		if(*p) p++;
		*p = 0;
	}
	
	if( (fp = fopen(filename, "wb+")) == NULL ) 
	{
		os_mkdir(filename, TRUE);
		if( (fp = fopen(filename, "wb+")) == NULL )
			return;
	}
	fwrite(buf, strlen(buf), 1, fp);
	fclose(fp);
}

INT setting_read_int(CHAR *filename, CHAR *key, INT def)
{
	CHAR buf[100];
	STRING *tmp;
	INT ret;
	sprintf(buf, "%d", def);
	tmp = setting_read(filename, key, buf);
	ret = atoi(tmp->str);
	string_free(tmp);

	return ret;
}

STRING *setting_read(CHAR *filename, CHAR *key, CHAR *def)
{
	
	STRING *str;
	CHAR *tmpbuf;
	CHAR *pvalue;

	os_lock_lock(settinglock);
	
	str = string_new(def);

	tmpbuf = setting_load_file(filename);

	setting_find_key(tmpbuf, key, &pvalue);
	setting_get_key_value(pvalue, str);

	os_free(tmpbuf);

	os_lock_unlock(settinglock);
	return str;
}

VOID setting_write_int(CHAR *filename, CHAR *key, INT value)
{
	CHAR buf[100];
	sprintf(buf, "%d", value);
	setting_write(filename, key, buf);
}

VOID setting_write(CHAR *filename, CHAR *key, CHAR *value)
{
	STRING *str;
	CHAR *tmpbuf;
	CHAR *pkey;
	CHAR *p;

	os_lock_lock(settinglock);	


	tmpbuf = setting_load_file(filename);
	str = string_new(tmpbuf);

	pkey = setting_find_key(tmpbuf, key, NULL);

	if(pkey != NULL)
	{
		string_truncate(str, pkey - tmpbuf);
		str = string_append(str, key);
		str = string_append(str, "=");
		str = string_append(str, value);
		str = string_append(str, "\r\n");

		p = strstr(pkey, "\n");
		if(p)
			str = string_append(str, p + 2);
		else
			str = string_append(str, "\n\n");
	}
	else
	{
		str = string_append(str, key);
		str = string_append(str, "=");
		str = string_append(str, value);
		str = string_append(str, "\r\n");
	}

	os_free(tmpbuf);

	setting_save_file(filename, str->str);
	string_free(str);
	
	os_lock_unlock(settinglock);
}



VOID setting_init()
{
	settinglock = os_lock_create();
}

VOID setting_cleanup()
{
	settinglock = os_lock_free(settinglock);
}
